/**
 * 
 */
package com.ac4j.parser;

import java.awt.image.BufferedImage;
import java.util.ArrayList;

import com.ac4j.algorithm.AbstractRepickingAlgorithm;
import com.ac4j.algorithm.AbstractStrategy;
import com.ac4j.algorithm.AllLocating;
import com.ac4j.algorithm.BrutalforceStrategyWithThreshold;
import com.ac4j.algorithm.MaxiumScoreRepicking;
import com.ac4j.algorithm.TemplateRecognize;
import com.ac4j.match.Match;
import com.ac4j.sample.Sample;
import com.ac4j.sample.SampleImage;
import com.ac4j.utility.BufferedImageUtility;

/**
 * @author Administrator
 * 
 */
public class Koubei implements IParser {
	ArrayList<Sample> standardsamples;
	ArrayList<Sample> weaksamples;

	/**
	 * Construct a new <code>Koubei</code> class, which could parse phone image
	 * on <link>www.koubei.com</link>.
	 * 
	 */
	public Koubei() {
		// TODO Auto-generated constructor stub
	}

	/**
	 * Construct a new <code>Koubei</code> class with custom samples, which
	 * could parse phone image on <link>www.koubei.com</link>.
	 * 
	 * @param standardsamples
	 *            Customize standard samples (0,1,2,..,9)
	 * @param weaksamples
	 *            Customize weak samples (-,(,))
	 */
	public Koubei(ArrayList<Sample> standardsamples,
			ArrayList<Sample> weaksamples) {
		super();
		this.standardsamples = standardsamples;
		this.weaksamples = weaksamples;
	}

	private ArrayList<Sample> GetDefaultSamples() {
		String text;
		Byte[][] value;
		Sample s;
		ArrayList<Sample> slist = new ArrayList<Sample>();

		text = "0";
		value = new Byte[][] { { 0, 1, 1, 1, 1, 0 }, { 1, 1, 0, 0, 1, 1 },
				{ 1, 0, 0, 0, 0, 1 }, { 1, 0, 0, 0, 0, 1 },
				{ 1, 0, 0, 0, 0, 1 }, { 1, 0, 0, 0, 0, 1 },
				{ 1, 0, 0, 0, 0, 1 }, { 1, 1, 0, 0, 1, 1 },
				{ 0, 1, 1, 1, 1, 0 } };
		s = new Sample(new SampleImage(value, 6, 9), text);
		slist.add(s);

		text = "1";
		value = new Byte[][] { { 0, 0, 0, 1, 0 }, { 0, 0, 1, 1, 0 },
				{ 0, 1, 0, 1, 0 }, { 0, 0, 0, 1, 0 }, { 0, 0, 0, 1, 0 },
				{ 0, 0, 0, 1, 0 }, { 0, 0, 0, 1, 0 }, { 0, 0, 0, 1, 0 },
				{ 0, 0, 0, 1, 0 } };
		s = new Sample(new SampleImage(value, 5, 9), text);
		slist.add(s);

		text = "2";
		value = new Byte[][] { { 0, 1, 1, 1, 1, 0 }, { 1, 1, 0, 0, 1, 1 },
				{ 1, 0, 0, 0, 0, 1 }, { 0, 0, 0, 0, 1, 1 },
				{ 0, 0, 0, 0, 1, 0 }, { 0, 0, 1, 1, 0, 0 },
				{ 0, 1, 1, 0, 0, 0 }, { 0, 1, 0, 0, 0, 0 },
				{ 1, 1, 1, 1, 1, 1 } };
		s = new Sample(new SampleImage(value, 6, 9), text);
		slist.add(s);

		text = "3";
		value = new Byte[][] { { 0, 0, 1, 1, 1, 0 }, { 1, 1, 0, 0, 1, 1 },
				{ 0, 0, 0, 0, 0, 1 }, { 0, 0, 0, 1, 1, 0 },
				{ 0, 0, 0, 0, 1, 1 }, { 0, 0, 0, 0, 0, 1 },
				{ 1, 0, 0, 0, 0, 1 }, { 0, 1, 0, 0, 1, 1 },
				{ 0, 1, 1, 1, 1, 0 } };
		s = new Sample(new SampleImage(value, 6, 9), text);
		slist.add(s);

		text = "4";
		value = new Byte[][] { { 0, 0, 0, 0, 1, 0, 0 },
				{ 0, 0, 0, 1, 1, 0, 0 }, { 0, 0, 1, 1, 1, 0, 0 },
				{ 0, 0, 1, 0, 1, 0, 0 }, { 0, 1, 0, 0, 1, 0, 0 },
				{ 1, 0, 0, 0, 1, 0, 0 }, { 1, 1, 1, 1, 1, 1, 1 },
				{ 0, 0, 0, 0, 1, 0, 0 }, { 0, 0, 0, 0, 1, 0, 0 } };
		s = new Sample(new SampleImage(value, 7, 9), text);
		slist.add(s);

		text = "5";
		value = new Byte[][] { { 0, 1, 1, 1, 1, 1 }, { 0, 1, 0, 0, 0, 0 },
				{ 1, 1, 0, 0, 0, 0 }, { 1, 1, 1, 1, 1, 0 },
				{ 1, 0, 0, 0, 1, 1 }, { 0, 0, 0, 0, 0, 1 },
				{ 1, 0, 0, 0, 0, 1 }, { 1, 1, 0, 0, 1, 1 },
				{ 0, 1, 1, 1, 1, 0 } };
		s = new Sample(new SampleImage(value, 6, 9), text);
		slist.add(s);

		text = "6";
		value = new Byte[][] { { 0, 0, 1, 1, 1, 0 }, { 0, 1, 0, 0, 1, 1 },
				{ 1, 0, 0, 0, 0, 0 }, { 1, 0, 1, 1, 1, 0 },
				{ 1, 1, 0, 0, 1, 1 }, { 1, 0, 0, 0, 0, 1 },
				{ 1, 0, 0, 0, 0, 1 }, { 1, 1, 0, 0, 1, 1 },
				{ 0, 1, 1, 1, 1, 0 } };
		s = new Sample(new SampleImage(value, 6, 9), text);
		slist.add(s);

		text = "7";
		value = new Byte[][] { { 1, 1, 1, 1, 1, 1 }, { 0, 0, 0, 0, 1, 1 },
				{ 0, 0, 0, 0, 1, 0 }, { 0, 0, 0, 1, 0, 0 },
				{ 0, 0, 0, 1, 0, 0 }, { 0, 0, 1, 1, 0, 0 },
				{ 0, 0, 1, 0, 0, 0 }, { 0, 0, 1, 0, 0, 0 },
				{ 0, 0, 1, 0, 0, 0 } };
		s = new Sample(new SampleImage(value, 6, 9), text);
		slist.add(s);

		text = "8";
		value = new Byte[][] { { 0, 1, 1, 1, 1, 0 }, { 1, 0, 0, 0, 1, 1 },
				{ 1, 0, 0, 0, 0, 1 }, { 0, 1, 1, 1, 1, 0 },
				{ 1, 1, 0, 0, 1, 1 }, { 1, 0, 0, 0, 0, 1 },
				{ 1, 0, 0, 0, 0, 1 }, { 1, 1, 0, 0, 1, 1 },
				{ 0, 1, 1, 1, 1, 0 } };
		s = new Sample(new SampleImage(value, 6, 9), text);
		slist.add(s);

		text = "9";
		value = new Byte[][] { { 0, 1, 1, 1, 0, 0 }, { 1, 1, 0, 0, 1, 0 },
				{ 1, 0, 0, 0, 0, 1 }, { 1, 0, 0, 0, 0, 1 },
				{ 1, 1, 0, 0, 1, 1 }, { 0, 1, 1, 1, 0, 1 },
				{ 0, 0, 0, 0, 0, 1 }, { 1, 1, 0, 0, 1, 0 },
				{ 0, 1, 1, 1, 0, 0 } };
		s = new Sample(new SampleImage(value, 6, 9), text);
		slist.add(s);

		return slist;
	}

	private ArrayList<Sample> GetDefaultWeakSamples() {
		String text;
		Byte[][] value;
		Sample s;
		ArrayList<Sample> slist = new ArrayList<Sample>();

		text = "-";
		value = new Byte[][] { { 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 0, 0, 0, 0 },
				{ 0, 0, 0, 0 }, { 0, 0, 0, 0 }, { 1, 1, 1, 1 }, { 0, 0, 0, 0 },
				{ 0, 0, 0, 0 }, { 0, 0, 0, 0 } };
		s = new Sample(new SampleImage(value, 4, 9), text);
		slist.add(s);

		return slist;

	}

	/**
	 * @return the standardsamples
	 */
	public ArrayList<Sample> getStandardsamples() {
		return standardsamples;
	}

	/**
	 * @return the weaksamples
	 */
	public ArrayList<Sample> getWeaksamples() {
		return weaksamples;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see com.ac4j.parser.IParser#ParseImage(java.awt.image.BufferedImage)
	 */
	public String ParseImage(BufferedImage sourceimg) {
		if (standardsamples == null)
			standardsamples = this.GetDefaultSamples();
		if (weaksamples == null)
			weaksamples = this.GetDefaultWeakSamples();

		SampleImage simg = BufferedImageUtility.BinarizateToSampleImage(
				sourceimg, 128);
		simg = simg.Chop(1, 0, simg.getWidth(), 9);

		// Standard Strategy
		AbstractStrategy standardstrategy = new BrutalforceStrategyWithThreshold(
				new AllLocating(simg), new TemplateRecognize(), simg,
				standardsamples, 0.86f);

		// Weak Strategy
		AbstractStrategy weakstrategy = new BrutalforceStrategyWithThreshold(
				new AllLocating(simg), new TemplateRecognize(), simg,
				weaksamples, 0.95f);

		ArrayList<Match> stdmatchlist = standardstrategy.Execute();
		ArrayList<Match> weakmatchlist = weakstrategy.Execute();

		stdmatchlist.addAll(weakmatchlist);

		AbstractRepickingAlgorithm picker = new MaxiumScoreRepicking();
		String r = picker.GetBestCandidateResult(stdmatchlist)
				.getResultString();
		return r;

	}

	/**
	 * @param standardsamples
	 *            the standardsamples to set
	 */
	public void setStandardsamples(ArrayList<Sample> standardsamples) {
		this.standardsamples = standardsamples;
	}

	/**
	 * @param weaksamples
	 *            the weaksamples to set
	 */
	public void setWeaksamples(ArrayList<Sample> weaksamples) {
		this.weaksamples = weaksamples;
	}

}
